<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'

defineProps<{
  phoneNumber: string
  disabled?: boolean
}>()

const emit = defineEmits<{
  (e: 'complete', code: string): void
  (e: 'resend'): void
}>()

const verifyCode = ref(['', '', '', '', '', ''])
const inputRefs = ref<HTMLInputElement[]>([])
const countdown = ref(0)
const countdownInterval = ref<number | null>(null)

// 处理输入事件
function handleInput(index: number, event: Event) {
  const target = event.target as HTMLInputElement
  const value = target.value

  // 确保只保留一个字符，且只允许数字
  const numericValue = value.replace(/\D/g, '')
  if (numericValue.length > 0) {
    verifyCode.value[index] = numericValue.slice(0, 1)
  }
  else {
    verifyCode.value[index] = ''
  }

  // 如果当前输入框有内容，且不是最后一个输入框，则自动聚焦到下一个输入框
  if (verifyCode.value[index] && index < 5) {
    inputRefs.value[index + 1].focus()
  }

  // 检查是否所有输入框都已填写
  const isComplete = verifyCode.value.every(v => v.length === 1)
  if (isComplete) {
    emit('complete', verifyCode.value.join(''))
  }
}

// 处理键盘事件
function handleKeyDown(index: number, event: KeyboardEvent) {
  // 如果按下删除键且当前输入框为空，则聚焦到前一个输入框
  if (event.key === 'Backspace' && !verifyCode.value[index] && index > 0) {
    inputRefs.value[index - 1].focus()
  }
}

// 粘贴验证码
function handlePaste(event: ClipboardEvent) {
  event.preventDefault()
  const pastedText = event.clipboardData?.getData('text') || ''
  const digits = pastedText.replace(/\D/g, '').split('').slice(0, 6)

  digits.forEach((digit, index) => {
    if (index < 6) {
      verifyCode.value[index] = digit
    }
  })

  // 聚焦到下一个空输入框或最后一个
  const nextEmptyIndex = verifyCode.value.findIndex(v => !v)
  if (nextEmptyIndex !== -1) {
    inputRefs.value[nextEmptyIndex].focus()
  }
  else if (digits.length > 0) {
    inputRefs.value[5].focus()

    // 如果填满了6位，触发完成事件
    if (verifyCode.value.every(v => v.length === 1)) {
      emit('complete', verifyCode.value.join(''))
    }
  }
}

// 清空验证码
function clearCode() {
  verifyCode.value = ['', '', '', '', '', '']
  inputRefs.value[0].focus()
}

// 重新发送验证码
function resendCode() {
  if (countdown.value > 0)
    return

  emit('resend')
  startCountdown()
}

// 开始倒计时
function startCountdown() {
  countdown.value = 60

  if (countdownInterval.value) {
    clearInterval(countdownInterval.value)
  }

  countdownInterval.value = window.setInterval(() => {
    countdown.value--
    if (countdown.value <= 0 && countdownInterval.value) {
      clearInterval(countdownInterval.value)
      countdownInterval.value = null
    }
  }, 1000)
}

// 组件挂载时自动聚焦第一个输入框
onMounted(() => {
  inputRefs.value[0]?.focus()
  startCountdown()
})

// 组件卸载时清理定时器
onBeforeUnmount(() => {
  if (countdownInterval.value) {
    clearInterval(countdownInterval.value)
  }
})

// 对外暴露的方法
defineExpose({
  clearCode,
})
</script>

<template>
  <div class="verify-code-container">
    <div class="verify-code-header">
      <div class="back-button">
        <slot name="back-button">
          <span>&lt;</span>
        </slot>
      </div>
      <h1 class="title">
        输入6位验证码
      </h1>
    </div>

    <div class="verify-code-info">
      <p class="info-text">
        验证码已发送至 {{ phoneNumber }}
      </p>
    </div>

    <div class="verify-code-inputs">
      <div
        v-for="(code, index) in verifyCode"
        :key="index"
        class="input-wrapper"
      >
        <input
          :ref="el => { if (el) inputRefs[index] = el as HTMLInputElement }"
          v-model="verifyCode[index]"
          type="text"
          inputmode="numeric"
          maxlength="1"
          :disabled="disabled"
          class="verification-input"
          :class="{ 'has-value': code }"
          @input="handleInput(index, $event)"
          @keydown="handleKeyDown(index, $event)"
          @paste="index === 0 && handlePaste($event)"
        >
      </div>
    </div>

    <div class="resend-container">
      <button
        class="resend-button"
        :disabled="countdown > 0"
        @click="resendCode"
      >
        {{ countdown > 0 ? `重新发送 ${countdown}s` : '重新发送' }}
      </button>
    </div>
  </div>
</template>

<style scoped>
.verify-code-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  margin: 0 auto;
  color: #333;
}

.verify-code-header {
  display: flex;
  align-items: center;
  width: 100%;
  position: relative;
  margin-bottom: 30px;
}

.back-button {
  position: absolute;
  left: 0;
  font-size: 24px;
  cursor: pointer;
}

.title {
  flex: 1;
  text-align: center;
  font-size: 24px;
  font-weight: 600;
  margin: 0;
}

.verify-code-info {
  width: 100%;
  text-align: center;
  margin-bottom: 40px;
  color: #999;
}

.info-text {
  font-size: 16px;
  margin: 0;
}

.verify-code-inputs {
  display: flex;
  justify-content: center;
  margin-bottom: 60px;
  width: 100%;
}

.input-wrapper {
  position: relative;
  width: 46px;
  margin-right: 10px;
  height: 46px;
  border-radius: 50%;
}

.verification-input {
  width: 100%;
  height: 100%;
  text-align: center;
  font-size: 20px;
  font-weight: 600;
  border: 1px solid #e0e0e0;
  border-radius: 50%;
  background-color: #f5f5f5;
  outline: none;
  transition: all 0.3s ease;
  color: #4285f4;
}

.verification-input:focus {
  border-color: #4285f4;
  background-color: rgba(66, 133, 244, 0.1);
}

.verification-input.has-value {
  border-color: #4285f4;
  background-color: #fff;
  color: #4285f4;
}

.resend-container {
  width: 100%;
  text-align: center;
}

.resend-button {
  background: none;
  border: none;
  color: #999;
  font-size: 16px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.resend-button:hover:not(:disabled) {
  color: #4285f4;
}

.resend-button:disabled {
  color: #ccc;
  cursor: not-allowed;
}
</style>
